/*
 * Copyright 2011-2023 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0.
 * See `LICENSE` in the project root for license information.
 */

package me.ijleex.platform.framework.entity;

import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;

/**
 * 操作返回结果
 *
 * <p>默认情况下，成功的返回码为 {@linkplain #OK 0}，失败为 {@linkplain #ERROR 1}，参数错误为 {@linkplain #INVALID_ARG -1}</p>
 *
 * @author liym
 */
public final class Result extends EntitySupport {

    /**
     * 成功
     */
    private static final int OK = 0;
    /**
     * 参数不合法
     */
    private static final int INVALID_ARG = -1;
    /**
     * 错误
     */
    private static final int ERROR = 1;

    /**
     * 状态码
     */
    private final int code;
    /**
     * 消息内容
     *
     * <p>可用于返回首选的结果内容</p>
     */
    private final Object msg;
    /**
     * 附加数据
     *
     * @since 2017-03-15 09:12:24
     */
    @JsonInclude(value = JsonInclude.Include.NON_EMPTY, content = JsonInclude.Include.NON_NULL)
    private final Map<String, Object> data;

    /**
     * 构造默认返回信息（失败）
     *
     * <p>该默认无参构造方法不能删除，因为使用 JSON 转实体对象时，依赖这个方法。</p>
     *
     * @see me.ijleex.platform.framework.json.util.JacksonUtils#jsonToObj(String, Class)
     */
    private Result() {
        // 操作失败，请联系管理员
        this(ERROR, "操作失败");
    }

    /**
     * 构造返回信息
     *
     * @param code 返回码
     * @param msg 信息/内容
     */
    private Result(int code, Object msg) {
        this.code = code;
        this.msg = msg;
        this.data = new ConcurrentHashMap<>(8);
    }

    /**
     * 获取状态码
     */
    public int getCode() {
        return this.code;
    }

    /**
     * 获取消息内容
     */
    public Object getMsg() {
        return this.msg;
    }

    /**
     * 获取附加数据
     */
    public Map<String, Object> getData() {
        return Collections.unmodifiableMap(this.data);
    }

    // ===

    /**
     * 添加额外数据
     *
     * @param name 数据名称
     * @param value 内容
     * @return 当前对象的实例
     */
    public Result addData(String name, Object value) {
        if (name == null || value == null) {
            return this;
        }
        try {
            this.data.put(name, value);
        } catch (Exception ignored) {
        }
        return this;
    }

    /**
     * 添加额外数据
     *
     * @param data 数据
     * @return 当前对象的实例
     * @since 2019-10-15 17:32:15
     */
    public Result addData(Map<String, Object> data) {
        if (data == null || data.isEmpty()) {
            return this;
        }
        try {
            this.data.putAll(data);
        } catch (Exception ignored) {
        }
        return this;
    }

    /**
     * 根据数据名称，获取返回数据
     *
     * @param name 数据名称
     * @return 数据内容
     * @since 2019-10-31 11:24
     */
    public Object getData(String name) {
        if (this.data.isEmpty()) {
            return null;
        }
        return this.data.get(name);
    }

    /**
     * 根据数据名称，获取返回数据
     *
     * @param name 数据名称
     * @param defaultValue 如果结果数据中不存在指定的 name，则返回默认值
     * @return 数据内容
     * @since 2020-04-23 21:27:11
     */
    public Object getData(String name, Object defaultValue) {
        if (this.data.isEmpty()) {
            return defaultValue;
        }
        return this.data.getOrDefault(name, defaultValue);
    }

    // ===

    /**
     * 构建错误消息（参数错误）
     *
     * @return 参数错误消息
     * @since 2019-01-30 10:42 新建
     */
    public static Result invalidArg(String msg) {
        return custom(INVALID_ARG, msg);
    }

    /**
     * 构建错误消息
     *
     * @return 错误消息
     */
    public static Result error() {
        return new Result();
    }

    /**
     * 构建错误消息
     *
     * @param msg 内容
     * @return 错误消息
     */
    public static Result error(String msg) {
        return custom(ERROR, msg);
    }

    /**
     * 构建指定返回码和消息的结果
     *
     * @param code 返回码，非 {@link #OK}
     * @param msg 信息
     * @return 错误消息
     */
    public static Result custom(int code, String msg) {
        return new Result(code, msg);
    }

    /**
     * 构建成功消息
     *
     * @return 成功消息
     */
    public static Result ok() {
        return ok("操作成功");
    }

    /**
     * 构建成功消息
     *
     * @param msg 消息内容
     * @return 成功消息
     */
    public static Result ok(Object msg) {
        return new Result(OK, msg);
    }

    /**
     * 根据新增、删除、更新等操作的结果，构建请求的返回结果
     *
     * @param rows 新增、删除、更新等操作影响数据的行数
     * @return 操作结果：rows>0，返回成功，否则失败
     * @since 2019-03-02 16:12 of affected rows
     */
    public static Result of(int rows) {
        return rows > 0 ? ok() : error();
    }

    /**
     * 根据操作结果（true/false），构建返回结果
     *
     * @param result 结果
     * @return 操作结果：true，返回成功，否则失败
     * @since 2019-03-02 16:13 of true/false
     */
    public static Result of(boolean result) {
        return result ? ok() : error();
    }

    // ===

    /**
     * 判断该结果是否成功
     *
     * @return true/false
     * @since 2019-01-30 15:03
     */
    @JsonIgnore
    public boolean isOk() {
        return this.code == OK;
    }

    /**
     * 显示结果信息
     */
    @Override
    public String toString() {
        return "Result[code=" + this.code + ", msg=" + this.msg + ']';
    }

}
